package uk.co.hephistocles.blobGame;

import java.util.LinkedList;
import java.util.LinkedList;

import com.badlogic.gdx.math.Vector3;

public class Bezier {
	public LinkedList<Vector3> controls;
	private static int count;
	private static LinkedList<Vector3> subdivide(LinkedList<Vector3> c, float t) {
		LinkedList<Vector3> returnVal = new LinkedList<Vector3>();
		
		for (int i=0; i<c.size()-1; i++) {
			Vector3 ans = new Vector3(
					c.get(i).x+(c.get(i+1).x - c.get(i).x)*t,
					c.get(i).y+(c.get(i+1).y - c.get(i).y)*t,
					c.get(i).z+(c.get(i+1).z - c.get(i).z)*t
				);
			returnVal.addLast(ans);
		}		
		return returnVal;
	}
	public static Vector3 getPos(LinkedList<Vector3> c, float t) {
		LinkedList<Vector3> val = subdivide(c,t);
		if (val.size() == 1) {
			return val.get(0);
		} else {
			return getPos(val,t);
		}
	}
	
	
	public Bezier(LinkedList<Vector3> p) {
		this.controls = p;
	}

	public Vector3 getPos(float t) {
		return getPos(controls,t);
	}
	
	public static LinkedList<Line> toLines(Bezier curve, float threshold) {
		LinkedList<Line> linesArr = new LinkedList<Line>();
		LinkedList<Bezier> curvesArr = new LinkedList<Bezier>();
		curvesArr.add(curve);
		while (curvesArr.size() >0 ) {
			Bezier bez = curvesArr.removeFirst();
			Vector3 a = bez.controls.getFirst().cpy();
			Vector3 b = bez.controls.getLast().cpy();
			Vector3 c = bez.getPos(0.5f);
			float base = a.dst(b);
	
			a.mul(-1);
			Vector3 ab = b.add(a);
			Vector3 ac = c.add(a);
			
			ab.crs(ac);
			float area = 0.5f*ab.len();
			
			float height = area/base;
			if (height< threshold) {
				linesArr.add(new Line(bez.controls.getFirst().x,bez.controls.getFirst().y,
						bez.controls.getLast().x,bez.controls.getLast().y,
						(Math.atan2(
								bez.controls.getFirst().y-bez.controls.getLast().y,
								bez.controls.getFirst().x-bez.controls.getLast().x)
						- Math.PI/2)));
			} else {
				Bezier[] newBez = bez.split(0.5f);
				curvesArr.add(newBez[0]);
				curvesArr.add(newBez[1]);
			}
		}
		return linesArr;
	}
	
	public static LinkedList<Line> toLines2(Bezier bez, float threshold) {
		LinkedList<Line> linesArr = new LinkedList<Line>();
		Vector3 a = bez.controls.getFirst();
		Vector3 b = bez.controls.getLast();
		Vector3 c = bez.getPos(0.5f);
		linesArr.add(new Line(a.x,a.y,b.x,b.y, (Math.atan2(a.y-b.y,a.x-b.x) - Math.PI/2)));
		return linesArr;
	}
	public Bezier[] split(float t) {
		Bezier[] curves = new Bezier[2];
		LinkedList<Vector3> val = controls;
		LinkedList<Vector3> bez0 = new LinkedList<Vector3>();
		LinkedList<Vector3> bez1 = new LinkedList<Vector3>();
		bez0.addLast(val.getFirst());
		bez1.addFirst(val.getLast());

		while (val.size()>1) {
			val = subdivide(val,t);
			bez0.addLast(val.getFirst());
			bez1.addFirst(val.getLast());
		}
		curves[0] = new Bezier(bez0);
		curves[1] = new Bezier(bez1);
		return curves;
	}
	
	public String toString() {
		return controls.toString();
	}
	
	public float getLength() {
		// TODO Auto-generated method stub
		return controls.size();
	}

}
